package cn.edu.zstu.qingzhu.qingzhushop.service.impl;

import cn.edu.zstu.qingzhu.qingzhushop.entity.AuthenticationUser;
import cn.edu.zstu.qingzhu.qingzhushop.entity.User;
import cn.edu.zstu.qingzhu.qingzhushop.entity.UserCount;
import cn.edu.zstu.qingzhu.qingzhushop.entity.VueRouteConfig;
import cn.edu.zstu.qingzhu.qingzhushop.exception.RegisterException;
import cn.edu.zstu.qingzhu.qingzhushop.mapper.ResourceMapper;
import cn.edu.zstu.qingzhu.qingzhushop.mapper.RoleMapper;
import cn.edu.zstu.qingzhu.qingzhushop.mapper.UserMapper;
import cn.edu.zstu.qingzhu.qingzhushop.mapper.UserRoleMapper;
import cn.edu.zstu.qingzhu.qingzhushop.provider.UCloudProvider;
import cn.edu.zstu.qingzhu.qingzhushop.service.IUserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import javafx.util.Pair;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author ShenTuZhiGang
 * @version 1.0.0
 * @date 2020-10-17 18:47
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements IUserService {
    @Autowired
    UserMapper userMapper;
    @Autowired
    RoleMapper roleMapper;
    @Autowired
    ResourceMapper resourceMapper;
    @Autowired
    UserRoleMapper userRoleMapper;
    @Autowired
    UCloudProvider uCloudProvider;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.loadUserByUserName(username);
        if (user == null) {
            throw new UsernameNotFoundException("账号不存在");
        }
        AuthenticationUser authenticationUser = new AuthenticationUser();
        BeanUtils.copyProperties(user, authenticationUser);
        authenticationUser.setRoles(roleMapper.getUserRolesByUid(user.getId()));
        return authenticationUser;
    }

    @Override
    public User registerUser(String username, String password) throws RegisterException {
        QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("username", username);
        if (userMapper.selectOne(objectQueryWrapper) != null) {
            throw new RegisterException("用户已存在");
        }
        User user = new User();
        user.setUsername(username);
        user.setPassword(passwordEncoder.encode(password));
        user.setPhone(username);
        user.setTelephone(username);
        user.setEnable(true);
        user.setLocked(false);
        if (save(user)) {
            userRoleMapper.insertUserRole(user.getId(), 3);
            return user;
        } else {
            throw new RegisterException("注册失败");
        }
    }

    @Override
    public boolean modifyPassword(String username, String oldPassword, String newPassword) {
        QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("username", username);
        User user = userMapper.selectOne(objectQueryWrapper);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        } else {
            if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
                throw new RuntimeException("密码错误");
            }
        }
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.eq("username", username);
        userUpdateWrapper.set("password", passwordEncoder.encode(newPassword));
        return true;
    }

    @Override
    public List<User> selectByUserPhone(String phone) {
        return userMapper.selectByUserPhone(phone);
    }

    @Override
    public AuthenticationUser getCurrentAuthenticationUser() {
        return ((AuthenticationUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal());
    }


    //根据用户名查询用户
    @Override
    public List<User> selectByUserName(String userName) {
        return userMapper.selectByUserName(userName);
    }

    //根据userId查找
    @Override
    public User selectByUserId(Integer id) {
        return userMapper.selectById(id);
    }


    @Override
    public int updateUserface(MultipartFile file, Integer id) {
        if (file.isEmpty()) {
            return 0;
        }
        String fileName = UUID.randomUUID() + file.getOriginalFilename();
        int size = (int) file.getSize();
        System.out.println(fileName + "-->" + size);
        try {
            String url = uCloudProvider.putStream(file.getInputStream(), file.getContentType(), fileName);
            User user = new User();
            user.setId(id);
            user.setUserface(url);
            updateById(user);
            return 1;
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return 0;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public List<User> getAllUserWithRoles() {
        return userMapper.getAllUsersWithRoles();
    }

    @Override
    public List<User> getAllUserWithRoles(String keyword) {
        return userMapper.getAllUsersWithRolesNoAuthenticationUserByKeyword(null, keyword);
    }

    @Override
    public List<User> getAllUserWithRoles(Integer userId, String keyword) {
        return userMapper.getAllUsersWithRolesNoAuthenticationUserByKeyword(userId, keyword);
    }

    @Override
    public List<VueRouteConfig> getVueRouteConfig(AuthenticationUser authenticationUser) {
        return VueRouteConfig.build(resourceMapper.getMenusByUserId(authenticationUser.getId()));
    }

    @Override
    @Transactional
    public boolean updateUserRole(Integer userId, Integer[] roleIds) {
        Map<String, Object> map = new HashMap<>();
        map.put("uid", userId);
        userRoleMapper.deleteByMap(map);
        for (Integer i :
                roleIds) {
            userRoleMapper.insertUserRole(userId, i);
        }
        return true;
    }


    @Override
    public List<UserCount> getUserCount() {
        return userMapper.selectUserCount();
    }


    @Override
    public Integer getSexCount(Integer query) {
        QueryWrapper queryWrapper = new QueryWrapper();
        if (query < 0) {
            queryWrapper.isNull("sex");
            queryWrapper.notIn("sex", 0, 1);
        } else {
            queryWrapper.eq("sex", query);
        }
        return userMapper.selectCount(queryWrapper);
    }

    @Override
    public Map<String, Integer> getUserDateAnalysis() {
        Map<String, Integer> userDateMap = new HashMap<>();
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        simpleDateFormat.applyPattern("yyyy-MM-dd");
        Integer dayCount = userMapper.getCountByDate("%Y-%m-%d", simpleDateFormat.format(date));
        userDateMap.put("day", dayCount);
        simpleDateFormat.applyPattern("yyyy-MM");
        Integer monthCount = userMapper.getCountByDate("%Y-%m", simpleDateFormat.format(date));
        userDateMap.put("month", monthCount);
        simpleDateFormat.applyPattern("yyyy");
        Integer yearCount = userMapper.getCountByDate("%Y", simpleDateFormat.format(date));
        userDateMap.put("year", yearCount);
        return userDateMap;
    }

    @Override
    public List<Pair<String, Integer>> getUserCityAnalysis() {
        return userMapper.getCountByCityIdLimit4();
    }

    @Override
    public boolean lockUser(Integer id, Integer lockStatus) {
        return false;
    }

}
